home *** CD-ROM | disk | FTP | other *** search
- #!/usr/local/bin/python
-
- # /***********************************************************
- # Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
- # Amsterdam, The Netherlands.
- #
- # All Rights Reserved
- #
- # Permission to use, copy, modify, and distribute this software and its
- # documentation for any purpose and without fee is hereby granted,
- # provided that the above copyright notice appear in all copies and that
- # both that copyright notice and this permission notice appear in
- # supporting documentation, and that the names of Stichting Mathematisch
- # Centrum or CWI not be used in advertising or publicity pertaining to
- # distribution of the software without specific, written prior permission.
- #
- # STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
- # THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- # FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
- # FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
- # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- #
- # ******************************************************************/
-
- # A tuner to control radio programs, by Jack Jansen.
-
- import sys
- import os
- import time
- import socket
- import time
- import string
- import getopt
- from stat import ST_MTIME
-
-
- RADIOCTLPORT=54320
- TRANSMITTERCTLPORT=54319
- CTLWS=socket.gethostname()
-
- # The list of networks to broadcast on, when looking for radio
- # stations. This should somehow be gotten differently.
- #
- MCASTLIST = ['192.16.184.0', '192.16.191.0', '192.16.201.255']
- # MCASTLIST = ['192.16.201.255']
-
- class struct(): pass
- info = struct()
-
- #
- # sendsock - send a message (and get optional reply)
- #
- def sendsock(host, port, msg, needrepl):
- try:
- host = socket.gethostbyname(host)
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- s.sendto(msg, (host,port))
- if needrepl:
- # Loop for max. 2.5 seconds waiting for a reply
- i = 0
- while i < 5 and not s.avail():
- time.millisleep(500)
- i = i + 1
- if not s.avail():
- print 'Radio program not responding'
- return ''
- return s.recv(500)
- except socket.error:
- print 'Incorrect radio settings'
- if needrepl:
- return ''
- else:
- return
- #
- # sendmulti - send a multicast message (and get replies)
- #
- def sendmulti(mcastlist, port, msg):
- rv = []
- try:
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- s.allowbroadcast(1)
- for host in mcastlist:
- s.sendto(msg, (host,port))
- # Loop for max. 2.5 seconds waiting for a reply
- i = 0
- while i < 25:
- time.millisleep(100)
- i = i + 1
- if s.avail():
- rv.append(s.recv(500))
- except socket.error:
- print 'Incorrect mcast settings'
- return rv
- #
- # getstationinfo - Return playlist, current and playing time (in minutes).
- # Returns a triple (playlist-filename, current record, playing time)
- #
- def getstationinfo(info):
- name = info[0]
- if len(info) > 3:
- playlist = info[3]
- else:
- playlist = '/ufs/' + name + '/CDlog'
- if len(info) > 5:
- since = eval(info[4])
- cur = string.joinfields(info[5:], ':')
- else:
- curfn = '/ufs/' + name + '/CD'
- try:
- curf = open(curfn,'r')
- cur = curf.readline()
- curf.close()
- except IOError:
- cur = '???'
- if cur[-1:] == '\n':
- cur = cur[:-1]
- try:
- sb = os.stat(curfn)
- since = time.time() - sb[ST_MTIME]
- except os.error:
- since = -1
- if since >= 0: since = since / 60 # Convert to minutes
- if since < 0:
- str = '??'
- elif since < 60:
- str = `since` + ' mins'
- else:
- since = since / 60
- if since < 24:
- str = `since` + ' hrs'
- else:
- str = `since / 24` + ' days'
- return playlist, cur, str
-
- #
- # updateinfo - Update one of the views with info on station 'name'
- #
- def printinfo(info):
- name = info[0]
- print 'Station '+ name + ':'
- print '\tPort ' + `info[1]`
- if name == '' or name[:3] == '???':
- print '\tNo information on station'
- else:
- try:
- p, c, t = getstationinfo(info)
- except IOError:
- return
- if c <> '' and c <> '???':
- print '\tCurrently playing: ' + c
- if t <> '??':
- print '\tSince: ' + t
- if p <> '':
- print '\tPlaylist in file: ' + p
-
- #
- # getstations - Return an array of (stationname, stationport)
- # listing all available stations.
- #
- def getstations():
- stations = []
- raw = sendmulti(MCASTLIST, TRANSMITTERCTLPORT, 'radio:s')
- for i in raw:
- if i[:7] == 'radio:S':
- fields = string.splitfields(i,':')[2:]
- fields[1] = string.atoi(fields[1])
- stations.append(fields)
- else:
- print 'Funny reply from transmitter:', i[:7]
- return stations
-
- #
- # getcurstation - Return (name,port) for station to which radio
- # on workstation ws is currently tuned to.
- #
- def getcurstation(stationlist, ws, port):
- rv = sendsock(ws, port, 'radio:i', 1)
- if rv == '':
- return ('',0)
- if rv[0:8] <> 'radio:I:':
- print 'Illegal reply from radio:',rv
- return ('',0)
- # Remove optional pause field
- rv = rv[8:]
- rv = string.splitfields(rv,':')
- if len(rv) == 1: # Old: port
- tport = string.atoi(rv[0])
- playing = 1
- elif len(rv) == 2: # newer: playing, port
- tport = string.atoi(rv[1])
- playing = string.atoi(rv[0])
- elif len(rv) == 3: # Still newer: playing, port, version
- tport = string.atoi(rv[1])
- playing = string.atoi(rv[0])
- else: # Too new
- print 'Unknown reply to info: ', rv
- for i in stationlist:
- if i[1] == tport:
- return (i, playing)
- return (('???(port '+`tport`+')' ,tport), playing)
-
- def main():
- radio_port = RADIOCTLPORT
- radio_ws = CTLWS
- try:
- optlist, args = getopt.getopt(sys.argv[1:], 'w:p:lLcPCT')
- mode = ''
- for o, a in optlist:
- if o == '-w':
- radio_ws = a
- elif o == '-p':
- radio_port = string.atoi(a)
- elif mode == '':
- mode = o[1]
- else:
- raise getopt.error
- if len(args) + len(mode) <> 1:
- raise getopt.error
- except getopt.error:
- print 'Usage: '+sys.argv[0]+' [options] command'
- print 'Options:'
- print '\t-w ws\tControl radio on workstation ws'
- print '\t-p port\tControl radio on port port'
- print 'Command:'
- print '\t-l\tList names of active stations'
- print '\t-L\tList names and info of active stations'
- print '\t-c\tList info on current station'
- print '\t-P\tTemporarily suspend radio, freeing port'
- print '\t-C\tContinue radio'
- print '\t-T\tToggle suspend/continue'
- print '\tstation\tTune to new station'
- sys.exit(1)
-
- #
- # First, do pause/continue command.
- #
- if mode == 'P':
- sendsock(radio_ws, radio_port, 'radio:0', 0)
- sys.exit(0)
- if mode == 'C':
- sendsock(radio_ws, radio_port, 'radio:1', 0)
- sys.exit(0)
- if mode == 'T':
- cn, playing = getcurstation([], radio_ws, radio_port)
- sendsock(radio_ws, radio_port, 'radio:'+`not playing`, 0)
- sys.exit(0)
- #
- # And list of new stations
- #
- stations = getstations()
- #
- # Set info for current station
- #
- if mode == '' or mode == 'c':
- cn, playing = getcurstation(stations,radio_ws, radio_port)
- if mode == 'l':
- for i in stations:
- print i[0]
- elif mode == 'L':
- for i in stations:
- printinfo(i)
- elif mode == 'c':
- printinfo(cn)
- else:
- for i in range(len(stations)):
- if stations[i][0] == args[0]:
- sendsock(radio_ws, radio_port, \
- 'radio:t:' + `stations[i][1]`, 0)
- sys.exit(0)
- print 'No such station: ', args[0]
-
-
-
- main()
-
- # Local variables:
- # py-indent-offset: 4
- # end:
-